let _Vue = null
export default class VueRouter {
  constructor (options) {
    this.options = options
    this.routeMap = {} // key: 路由地址, val: 对应组件
    this.data = _Vue.observable({ current: '' }) // 当前 hash 为 ""
  }

  static install (Vue) { // Vue: Vue 的构造函数
    // 1. 判断当前插件是否已经被安装
    if (VueRouter.install.installed) return
    VueRouter.install.installed = true

    // 2. 把 Vue 构造函数注册到全局变量中 (router 模块的函数作用域下)
    _Vue = Vue

    // 3. 把第一个创建的 Vue 实例时传入的 router 对象注入到所有 Vue 实例上
    _Vue.mixin({ // 接下来所有的 Vue 实例都被混入了一个 beforeCreate 钩子
      beforeCreate () {
        // 但是并不是每个 Vue 实例都要执行这个钩子, 它只应该执行一次, 所以加个判断:
        if (this.$options.router) { // 只有第一个 Vue 实例有这个 router 属性
          _Vue.prototype.$router = this.$options.router
          this.$options.router.init() // 初始化这个全局唯一 router 实例
        }
      }
    })
  }

  init () {
    this.createRouteMap()
    this.initComponents()
    this.initEvent()
  }

  createRouteMap () { // options.routes 数组 -> routeMap 键值对
    this.options.routes.forEach(route => {
      this.routeMap[route.path] = route.component
    })
  }

  initEvent () {
    window.addEventListener('hashchange', function () {
      this.data.current = window.location.hash
    })
    window.addEventListener('click', function(e) {
      if (e.target.nodeName === 'a') { // 处理一下 a 标签
        location.href = '#' + e.target.href
        // this.$router.data.current = e.target.href
        e.preventDefault()
      }
    })
  }

  initComponents () { // router-link &  router-view
    Vue.component('router-link', {
      props: {
        to: String
      },
      methods: {
        clickHandler (e) {
          location.href = '#' + this.to
          // this.$router.data.current = this.to
          e.preventDefault()
        }
      },
      render (h) {
        return h('a', {
          attrs: { href: this.to },
          on: { click: this.clickHandler }
        }, [this.$slots.default])
      }
    })

    const that = this
    Vue.component('router-view', {
      render (h) {
        // 1. 找到当前路由的地址
        const current = that.data.current
        // 3. 再根据地址从 routeMap 中找到对应的 view 组件
        const view = that.routeMap[current]
        // 3. 再把这个 view 组件转为虚拟 dom 直接返回
        return h(view)
      }
    })
  }
}
